package com.example.bigdemo.sercive.Impl;

import com.example.bigdemo.pojo.Values;
import com.example.bigdemo.sercive.Trapservice;
import com.example.bigdemo.tools.pingNet;
import com.example.bigdemo.trapMode.Start;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MessageProcessingModel;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.PDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Data
@Slf4j
public class TrapserviceImpl implements Trapservice {
   Logger Traplogger = LoggerFactory.getLogger(TrapserviceImpl.class);
    @Autowired
    Start start;
    @Autowired
    pingNet pingNet;

    @Override
    public CommandResponderEvent GetTrapMessage() throws InterruptedException {

        return start.startTrap();
    }
    public String pingNet(String ip) throws Exception {
        return pingNet.ping(ip);
    }
    public Boolean GetTrapMesssage() throws InterruptedException {
        log.info("启动处理线程");
        log.info("启动监听线程");
        return true;
    }
    public static String GetIntNetflow(String ip)  {
        String variableString = "";
        try{
            //设定CommunityTarget
            CommunityTarget myTarget = new CommunityTarget();
            //机器的地址
            Address address = GenericAddress.parse("udp:"+ip+"/161");
            //设定地址
            myTarget.setAddress(address);
            //设置snmp共同体
            myTarget.setCommunity(new OctetString("public"));
            //设置超时重试次数
            myTarget.setRetries(2);
            //设置超时的时间
            myTarget.setTimeout(5*60);
            //设置使用的snmp版本
            myTarget.setVersion(SnmpConstants.version2c);
            //设定采取的协议
            TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
            //调用TransportMapping中的listen()方法，启动监听进程，接收消息，由于该监听进程是守护进程，最后应调用close()方法来释放该进程
            transport.listen();
            //创建SNMP对象，用于发送请求PDU
            Snmp protocol = new Snmp(transport);
            //创建请求pdu,获取mib
            PDU request = new PDU();
            //调用的add方法绑定要查询的OID1.3.6.1.2.1.31.1.1.1.6
            request.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.10.3")));

            //调用setType()方法来确定该pdu的类型
            request.setType(PDU.GET);
            //调用 send(PDU pdu,Target target)发送pdu，返回一个ResponseEvent对象
            ResponseEvent responseEvent = protocol.send(request, myTarget);
            //通过ResponseEvent对象来获得SNMP请求的应答pdu，方法：public PDU getResponse()
            PDU response=responseEvent.getResponse();
            //输出
            if(response != null){
                //通过应答pdu获得mib信息（之前绑定的OID的值），方法：VaribleBinding get(int index)
                VariableBinding vb = response.get(0);
                response.getRequestID();
//               System.out.println(vb);
//                System.out.println(response);
                variableString = String.valueOf(vb.getVariable());
                //调用close()方法释放该进程
                transport.close();
            }

        }catch(IOException e){
            e.printStackTrace();
        }
        System.out.println(variableString);
        return variableString;
    }
    public static String GetOutNetflow(String ip)  {
        String variableString = "";
        try{
            //设定CommunityTarget
            CommunityTarget myTarget = new CommunityTarget();
            //机器的地址
            Address address = GenericAddress.parse("udp:"+ip+"/161");
            //设定地址
            myTarget.setAddress(address);
            //设置snmp共同体
            myTarget.setCommunity(new OctetString("public"));
            //设置超时重试次数
            myTarget.setRetries(2);
            //设置超时的时间
            myTarget.setTimeout(5*60);
            //设置使用的snmp版本
            myTarget.setVersion(SnmpConstants.version2c);
            //设定采取的协议
            TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
            //调用TransportMapping中的listen()方法，启动监听进程，接收消息，由于该监听进程是守护进程，最后应调用close()方法来释放该进程
            transport.listen();
            //创建SNMP对象，用于发送请求PDU
            Snmp protocol = new Snmp(transport);
            //创建请求pdu,获取mib
            PDU request = new PDU();
            //调用的add方法绑定要查询的OID
            request.add(new VariableBinding(new OID(" 1.3.6.1.2.1.2.2.1.16.3")));
            //调用setType()方法来确定该pdu的类型
            request.setType(PDU.GET);
            //调用 send(PDU pdu,Target target)发送pdu，返回一个ResponseEvent对象
            ResponseEvent responseEvent = protocol.send(request, myTarget);
            //通过ResponseEvent对象来获得SNMP请求的应答pdu，方法：public PDU getResponse()
            PDU response=responseEvent.getResponse();
            //输出
            if(response != null){
                //通过应答pdu获得mib信息（之前绑定的OID的值），方法：VaribleBinding get(int index)
                VariableBinding vb = response.get(0);
//                System.out.println(vb);
//                System.out.println(response);
                variableString = String.valueOf(vb.getVariable());
                //调用close()方法释放该进程
                transport.close();
            }

        }catch(IOException e){
            e.printStackTrace();
        }

        System.out.println(variableString);
        return variableString;
    }
    public Map<String, String> Getflow(String ip) throws InterruptedException {
        Map<String, String> flows =new HashMap<>();

        String intflow = TrapserviceImpl.GetIntNetflow("localhost");
        String outflow = TrapserviceImpl.GetOutNetflow("localhost");
        Thread.sleep(10 * 1000);
        String intflow2 = TrapserviceImpl.GetIntNetflow("localhost");
        String outflow2 = TrapserviceImpl.GetOutNetflow("localhost");

        if (intflow==null | outflow==null |intflow2==null | outflow2==null|
        "Null".equals(intflow)|"Null".equals(intflow2)|"Null".equals(outflow)||"Null".equals(outflow2)|
                intflow=="Null" | outflow=="Null" |intflow2=="Null" | outflow2=="Null"
        ){
            flows.put("error","交换机服务错误或者此设备为非交换机");
            return flows;
        }else{
            int intflownum = Integer.valueOf(intflow).intValue();
            int outflownum = Integer.valueOf(outflow).intValue();
            int intflownum2 = Integer.valueOf(intflow2).intValue();
            int outflownum2 = Integer.valueOf(outflow2).intValue();


            int cutint=intflownum - intflownum2;
            int cutout=outflownum - outflownum2;

            int intcut = Math.abs(cutint);
            int outcut = Math.abs(cutout);


          Double intflows= flowcunt(intcut,10);
           Double outflows=flowcunt(outcut,10);
           System.out.println("in流量速率:   "+intflows);
            System.out.println("out流量速率:  "+outflows);
           flows.put("下载流量速率(kb/s)", String.valueOf(intflows));
            flows.put("上传流量速率(kb/s)", String.valueOf(outflows));
            return flows;
        }

    }
    public static Double flowcunt(int num, int time){
        int num8=8*num;
        int cu=time*1024*1024;
        Double r= Double.valueOf(num8)/cu;
        String s = String.format("%.3f", r*128);
         r= Double.parseDouble(s);

        return r;
    }
    public String Getloss(String ip) {

        String variableString = null;
        Values R = null;
        TransportMapping transport = null ;
        Snmp snmp = null ;
        CommunityTarget target;
        String[] IF_OIDS =
                {"1.3.6.1.2.1.2.2.1.1",  //Index
                        "1.3.6.1.2.1.2.2.1.2",  //descr
                        "1.3.6.1.2.1.2.2.1.3",  //type
                        "1.3.6.1.2.1.2.2.1.5",  //speed
                        "1.3.6.1.2.1.2.2.1.6",  //mac
                        "1.3.6.1.2.1.2.2.1.7",  //adminStatus
                        "1.3.6.1.2.1.2.2.1.8",  //operStatus

                        "1.3.6.1.2.1.2.2.1.10", //inOctets
                        "1.3.6.1.2.1.2.2.1.16", //outOctets
                        "1.3.6.1.2.1.2.2.1.14", //inError
                        "1.3.6.1.2.1.2.2.1.20", //outError
                        "1.3.6.1.2.1.2.2.1.13", //inDiscard
                        "1.3.6.1.2.1.2.2.1.19", //outDiscard
                        "1.3.6.1.2.1.2.2.1.11", //inUcastPkts
                        "1.3.6.1.2.1.2.2.1.17", //outUcastPkts
                        "1.3.6.1.2.1.2.2.1.12", //inNUcastPkts
                        "1.3.6.1.2.1.2.2.1.18"};//outNUcastPkts

        try {
            transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            snmp.listen();
            target = new CommunityTarget();
            target.setCommunity(new OctetString("public"));
            target.setRetries(2);
            target.setAddress(GenericAddress.parse("udp:"+ip+"/161"));
            target.setTimeout(8000);
            target.setVersion(SnmpConstants.version2c);
            TableUtils tableUtils = new TableUtils(snmp, new PDUFactory() {
                @Override
                public PDU createPDU(Target arg0) {
                    PDU request = new PDU();
                    request.setType(PDU.GET);
                    return request;
                }
                @Override
                public PDU createPDU(MessageProcessingModel messageProcessingModel) {
                    PDU request = new PDU();
                    request.setType(PDU.GET);
                    return request;
                }

            });
            OID[] columns = new OID[IF_OIDS.length];
            for (int i = 0; i < IF_OIDS.length; i++)
                columns[i] = new OID(IF_OIDS[i]);
            @SuppressWarnings("unchecked")
            List<TableEvent> list = tableUtils.getTable(target, columns, null, null);
            if(list.size()==1 && list.get(0).getColumns()==null){
                variableString="0%";
            }else{
                for(TableEvent event : list){

                    VariableBinding[] values = event.getColumns();
                    if(values == null) continue;
                    String inpkg = values[13].getVariable().toString();
                    String outpkg = values[14].getVariable().toString();
                    int in = Integer.valueOf(inpkg).intValue();
                    int out = Integer.valueOf(outpkg).intValue();
                    int loss =0;
                    if(in - out == 0){
                       loss =0;
                    }else {
                        loss = (in - out) / (in * 100);
                    }

                    variableString=loss+"%";

                }
            }

        } catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                if(transport!=null)
                    transport.close();
                if(snmp!=null)
                    snmp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return variableString;
    }

}
